package org.ecpkn.PAGridSim.core.report;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.ecpkn.PAGridSim.core.configuration.Configuration;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.CategoryItemEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRendererState;
import org.jfree.chart.renderer.category.GanttRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.gantt.GanttCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.ui.RectangleEdge;

public class GanttRendererWithColor extends GanttRenderer {

	private final TaskSeriesCollection model;
	private int row;
	private int col;
	private int index;
	private static List<Color> clut = new ArrayList<Color>();
	static {
		int taskNumber = Configuration.getInstance().getParameterInt(
				Configuration.Const.SIMULATION_TASKNUMBER);
		Random rand = new Random();
		for (int c = 0; c < taskNumber; c++) {
			float r = rand.nextFloat();
			float g = rand.nextFloat();
			float b = rand.nextFloat();
			Color randomColor = new Color(r, g, b);
			clut.add(randomColor);
		}
		clut.add(Color.white);
	}

	public GanttRendererWithColor(TaskSeriesCollection model) {
		super();
		setIncludeBaseInRange(false);
		this.model = model;
		this.setBaseItemLabelGenerator(new CustomizedCategoryItemLabelGenerator());
	}

	protected void drawTasks(Graphics2D g2, CategoryItemRendererState state,
			Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
			ValueAxis rangeAxis, GanttCategoryDataset dataset, int row,
			int column) {

		int count = dataset.getSubIntervalCount(row, column);
		if (count == 0) {
			drawTask(g2, state, dataArea, plot, domainAxis, rangeAxis, dataset,
					row, column);
		}

		for (int subinterval = 0; subinterval < count; subinterval++) {

			RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();

			// value 0
			Number value0 = dataset.getStartValue(row, column, subinterval);
			if (value0 == null) {
				return;
			}
			double translatedValue0 = rangeAxis.valueToJava2D(
					value0.doubleValue(), dataArea, rangeAxisLocation);

			// value 1
			Number value1 = dataset.getEndValue(row, column, subinterval);
			if (value1 == null) {
				return;
			}
			double translatedValue1 = rangeAxis.valueToJava2D(
					value1.doubleValue(), dataArea, rangeAxisLocation);

			if (translatedValue1 < translatedValue0) {
				double temp = translatedValue1;
				translatedValue1 = translatedValue0;
				translatedValue0 = temp;
			}

			double rectStart = calculateBarW0(plot, plot.getOrientation(),
					dataArea, domainAxis, state, row, column);
			double rectLength = Math.abs(translatedValue1 - translatedValue0);
			double rectBreadth = state.getBarWidth();

			// DRAW THE BARS...
			Rectangle2D bar = null;

			if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
				bar = new Rectangle2D.Double(translatedValue0, rectStart,
						rectLength, rectBreadth);
			} else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
				bar = new Rectangle2D.Double(rectStart, translatedValue0,
						rectBreadth, rectLength);
			}

			Rectangle2D completeBar = null;
			Rectangle2D incompleteBar = null;
			Number percent = dataset.getPercentComplete(row, column,
					subinterval);
			double start = getStartPercent();
			double end = getEndPercent();
			if (percent != null) {
				double p = percent.doubleValue();
				if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
					completeBar = new Rectangle2D.Double(translatedValue0,
							rectStart + start * rectBreadth, rectLength * p,
							rectBreadth * (end - start));
					incompleteBar = new Rectangle2D.Double(translatedValue0
							+ rectLength * p, rectStart + start * rectBreadth,
							rectLength * (1 - p), rectBreadth * (end - start));
				} else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
					completeBar = new Rectangle2D.Double(rectStart + start
							* rectBreadth, translatedValue0 + rectLength
							* (1 - p), rectBreadth * (end - start), rectLength
							* p);
					incompleteBar = new Rectangle2D.Double(rectStart + start
							* rectBreadth, translatedValue0, rectBreadth
							* (end - start), rectLength * (1 - p));
				}

			}

			Paint seriesPaint = getItemPaint(row, column);
			g2.setPaint(seriesPaint);
			g2.fill(bar);

			if (completeBar != null) {
				g2.setPaint(getCompletePaint());
				g2.fill(completeBar);
			}
			if (incompleteBar != null) {
				g2.setPaint(getIncompletePaint());
				g2.fill(incompleteBar);
			}
			if (isDrawBarOutline()
					&& state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
				g2.setStroke(getItemStroke(row, column));
				g2.setPaint(getItemOutlinePaint(row, column));
				g2.draw(bar);
			}

			CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
					column);
			if (generator != null && isItemLabelVisible(row, column)) {
				drawItemLabel(g2, dataset, row, column, plot, generator, bar,
						false);
			}

			// collect entity and tool tip information...
			if (state.getInfo() != null) {
				EntityCollection entities = state.getEntityCollection();
				if (entities != null) {
					String tip = null;
					if (getToolTipGenerator(row, column) != null) {
						tip = getToolTipGenerator(row, column).generateToolTip(
								dataset, row, column);
					}
					String url = null;
					if (getItemURLGenerator(row, column) != null) {
						url = getItemURLGenerator(row, column).generateURL(
								dataset, row, column);
					}
					CategoryItemEntity entity = new CategoryItemEntity(bar,
							tip, url, dataset, dataset.getRowKey(row),
							dataset.getColumnKey(column));
					entities.add(entity);
				}
			}
		}
	}

	@Override
	public Paint getItemPaint(int row, int col) {
		if(Configuration.getInstance().getParameterBoolean(
				Configuration.Const.GANTT_SUBTASK_DIFCOLOR)){
			if (this.row != row || this.col != col) {
				this.row = row;
				this.col = col;
				index = 0;
			}
			Task t = (Task) model.getSeries(row).getTasks().get(col);
			int paTaskId;
			if (t.getSubtaskCount() != 0) {
				paTaskId = Integer.valueOf(t.getSubtask(index++).getDescription());
			} else {
				paTaskId = clut.size() - 1;
			}
			return clut.get(paTaskId);
		}else{
			return super.getItemPaint(row, col);
		}
		
	}

	public class CustomizedCategoryItemLabelGenerator implements
			CategoryItemLabelGenerator {
		private int index;
		private int series;
		private int categories;

		public CustomizedCategoryItemLabelGenerator() {
		}

		public String generateLabel(CategoryDataset dataSet, int series,
				int categories) {
			String label = "";
			if (Configuration.getInstance().getParameterBoolean(
					Configuration.Const.GANTT_SUBTASK_LABEL)) {
				if (this.series != series || this.categories != categories) {
					this.series = series;
					this.categories = categories;
					index = 0;
				}
				TaskSeriesCollection tsc = (TaskSeriesCollection) dataSet;
				Task t = (Task) tsc.getSeries(series).getTasks()
						.get(categories);
				if (t.getSubtaskCount() != 0) {
					label = t.getSubtask(index++).getDescription();
				} 
			}
			return label;
		}

		@Override
		public String generateColumnLabel(CategoryDataset dataset,
				int categories) {
			return dataset.getColumnKey(categories).toString();
		}

		@Override
		public String generateRowLabel(CategoryDataset dataset, int series) {
			return dataset.getRowKey(series).toString();
		}
	}
}